package org.gordonframework.core.process {
	import org.gordonframework.core.events.GProcessEvent;
	
	import flash.events.EventDispatcher;	

	/**
	 * @author sampet
	 */
	public class GParallel extends EventDispatcher implements GProcess {

		private var items:Array = [];

		private var _progress:Number = 0;		
		private var _running:Boolean = false;
		private var _complete:Boolean = false;

		private var numComplete:int;

		public function GParallel(...processes) {
			for(var i:uint = 0; i < processes.length ; i++) {
				addProcess( processes[i] );
			}			
		}

		/**
		 * The current progression of the parallel.
		 */
		public function get progress():Number {
			return _progress;
		}

		/**
		 * Indicates whether or not the parallel is running.
		 */
		public function get running():Boolean {
			return _running;
		}

		/**
		 * Indicates whether or not the parallel is complete.
		 */
		public function get complete():Boolean {
			return _complete;
		}

		/**
		 * Adds a process.
		 * 
		 * @param process The process to add.
		 */
		public function addProcess(process:GProcess):GProcess {
			if(process) {
				items.push( process );
			}
			return process;
		}		

		/**
		 * Starts the parallel.
		 */
		public function start():void {
			_running = true;
			_complete = false;
			_progress = 0;
			numComplete = 0;
			dispatchEvent( new GProcessEvent( GProcessEvent.START ) );	
			for each(var process:GProcess in items) {
				process.addEventListener( GProcessEvent.COMPLETE, processCompleteHandler );
				process.start( );
			}			
		}

		/**
		 * Stops the parallel if its running.
		 */
		public function stop():void {
			if(_running) {
				_running = false;
				_complete = false;
				_progress = 0;
				for each(var process:GProcess in items) {
					process.removeEventListener( GProcessEvent.COMPLETE, processCompleteHandler );				
					process.stop( );
				}
				dispatchEvent( new GProcessEvent( GProcessEvent.STOP ) );
			}			
		}

		private function processCompleteHandler(event:GProcessEvent):void {
			event.target.removeEventListener( GProcessEvent.COMPLETE, processCompleteHandler );	
			numComplete++;
			if(numComplete == items.length) {
				_running = false;
				_complete = true;
				_progress = 1;
				dispatchEvent( new GProcessEvent( GProcessEvent.COMPLETE ) );
			}
		}		
	}
}
